package com.ricky.utils;

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.lang.Class;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.log4j.Logger;
import org.dom4j.Element;

public class ConfigHelper {

	private static Logger log = Logger.getLogger(ConfigHelper.class);

	/**
	 * 解压文本对象为一个hashMap集合
	 * 
	 * @return
	 */
	@SuppressWarnings({ "unchecked" })
	public static <T> Map<String, T> decompression(Element root, String key,
			Class<? extends T> objClass) {
		Map<String, T> coll = new ConcurrentHashMap<String, T>();
		String keyv = "";

		for (Iterator<Element> it = root.elementIterator(objClass.getName()); it
				.hasNext();) {
			Element e = (Element) it.next();
			keyv = ((Element) e.element(key)).getText();
			T obj = parseObject(e);
			coll.put(keyv, obj);
		}
		return coll;
	}

	/**
	 * 解压文本对象为一个hashMap集合
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> Map<String, T> decompressionMap(String data, String key,
			Class<? extends T> objClass) {
		Map<String, T> coll = new ConcurrentHashMap<String, T>();
		T item = null;
		String[] rows = data.split("\r\n");// 所有行
		String[] property = rows[1].split("\t");// 第二行
		String rowStr;
		String[] columns;
		String keyv = "";
		int indexkey = 0;
		for (int ind = 0; ind < property.length; ind++) {
			if (property[ind].equals(indexkey))
				indexkey = ind;
		}

		for (int i = 2; i < rows.length; i++) {
			rowStr = rows[i];
			if (rowStr.indexOf("//") != -1)
				continue;

			columns = rowStr.split("\t");
			try {
				item = objClass.newInstance();
			} catch (InstantiationException e) {
				log.error(e.getMessage(), e);
			} catch (IllegalAccessException e) {
				log.error(e.getMessage(), e);
			}

			if (item instanceof Map) {
				for (int j = 0; j < property.length; j++) {
					if (columns.length > j)
						((Map<String, Object>) item).put(property[j],
								columns[j]);
				}
			} else if (item != null) {
				for (int j = 0; j < property.length; j++) {
					if (columns.length > j)
						setAttributeValue(item, property[j], columns[j]);
				}
			}

			keyv = columns[indexkey];

			if (item != null)
				coll.put(keyv, item);
		}

		return coll;
	}

	/**
	 * 解压文本为对象
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> decompression(String data,
			Class<? extends T> objClass) {
		List<T> coll = new CopyOnWriteArrayList<T>();
		T item = null;
		String[] rows = data.split("\r\n");// 所有行
		String[] property = rows[1].split("\t");// 第二行
		String rowStr;
		for (int i = 2; i < rows.length; i++) {
			rowStr = rows[i];
			if (rowStr.indexOf("//") != -1)
				continue;

			String[] columns = rowStr.split("\t");
			try {
				item = objClass.newInstance();
			} catch (InstantiationException e) {
				log.error(e.getMessage(), e);
			} catch (IllegalAccessException e) {
				log.error(e.getMessage(), e);
			}

			if (item instanceof Map) {
				for (int j = 0; j < property.length; j++) {
					if (columns.length > j)
						((Map<String, Object>) item).put(property[j],
								columns[j]);
				}
			} else if (item != null) {
				for (int j = 0; j < property.length; j++) {
					if (columns.length > j)
						setAttributeValue(item, property[j], columns[j]);
				}
			}

			if (item != null)
				coll.add(item);
		}

		return coll;
	}

	/**
	 * 将xml节点转换成对应的实体类
	 * 
	 * @param element
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T parseObject(Element element) {
		String className = element.getName();
		T obj = null;
		try {
			Class<T> cl = (Class<T>) Class.forName(className);
			obj = cl.newInstance();
		} catch (InstantiationException e) {
			log.error(e.getMessage(), e);
		} catch (IllegalAccessException e) {
			log.error(e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			log.error(e.getMessage(), e);
		}
		if (obj == null)
			return obj;
		List<Element> subElements = element.elements();
		for (Element sub : subElements) {
			setAttributeValue(obj, sub.getName(), sub.getText());
		}
		return obj;
	}

	@SuppressWarnings("unchecked")
	public static boolean setAttributeValue(Object obj, String name,
			String value) {
		try {
			Field f = getField(obj, name);
			f.setAccessible(true);
			@SuppressWarnings("rawtypes")
			Class fieldType = f.getType();
			if (fieldType == int.class) {
				if (value.length() > 0)
					f.setInt(obj, Integer.parseInt(value));
			} else if (fieldType == long.class) {
				f.setLong(obj, Long.parseLong(value));
			} else if (fieldType == boolean.class) {
				if (value.equals("0")) {
					f.setBoolean(obj, false);
				} else if (value.equals("1")) {
					f.setBoolean(obj, true);
				} else {
					f.setBoolean(obj, Boolean.parseBoolean(value));
				}
			} else if (fieldType == float.class) {
				f.setFloat(obj, Float.valueOf(value).floatValue());
			} else if (fieldType == double.class) {
				f.setDouble(obj, Double.valueOf(value).doubleValue());
			} else if (fieldType == String.class) {
				f.set(obj, value);
			} else if (fieldType.isEnum()) {
				f.set(obj, Enum.valueOf(fieldType, value));
			} else {

			}
			return true;
		} catch (NoSuchFieldException e) {
			log.error(e.getMessage(), e);
			;
		} catch (SecurityException e) {
			log.error(e.getMessage(), e);
		} catch (IllegalAccessException e) {
			log.error(e.getMessage(), e);
		}
		return false;
	}

	/**
	 * 得到属性
	 * 
	 * @param obj
	 * @param name
	 * @return
	 */
	public static Object getAttributeValue(Object obj, String name) {
		String field = Character.toUpperCase(name.charAt(0))
				+ name.substring(1);
		String prop = "get" + field;
		Object re = null;
		try {
			Method method = obj.getClass().getMethod(prop, new Class[]{});
			re = method.invoke(obj,new Object[]{});
			return re;
		} catch (IllegalArgumentException e) {
			log.error(e.getMessage(), e);
		} catch (IllegalAccessException e) {
			log.error(e.getMessage(), e);
		} catch (InvocationTargetException e) {
			log.error(e.getMessage(), e);
		} catch (SecurityException e) {
			log.error(e.getMessage(), e);
		} catch (NoSuchMethodException e) {
			log.error(e.getMessage(), e);
		}

		return null;
	}

	@SuppressWarnings("unchecked")
	public static boolean setAttributeValue(Object obj, String name,
			Object value) {
		try {
			Field f = getField(obj, name);
			f.setAccessible(true);
			@SuppressWarnings("rawtypes")
			Class fieldType = f.getType();
			if (fieldType == int.class) {
				// if(value.length()>0)
				f.setInt(obj, Integer.parseInt(value.toString()));
			} else if (fieldType == long.class) {
				f.setLong(obj, Long.parseLong(value.toString()));
			} else if (fieldType == boolean.class) {
				if (value.equals("0")) {
					f.setBoolean(obj, false);
				} else if (value.equals("1")) {
					f.setBoolean(obj, true);
				} else {
					f.setBoolean(obj, Boolean.parseBoolean(value.toString()));
				}
			} else if (fieldType == float.class) {
				f.setFloat(obj, Float.valueOf(value.toString()).floatValue());
			} else if (fieldType == double.class) {
				f.setDouble(obj, Double.valueOf(value.toString()).doubleValue());
			} else if (fieldType == String.class) {
				f.set(obj, value);
			} else if (fieldType.isEnum()) {
				f.set(obj, Enum.valueOf(fieldType, value.toString()));
			} else {
				f.set(obj, value);
			}
			return true;
		} catch (NoSuchFieldException e) {
			log.error(e.getMessage(), e);
			;
		} catch (SecurityException e) {
			log.error(e.getMessage(), e);
		} catch (IllegalAccessException e) {
			log.error(e.getMessage(), e);
		}
		return false;
	}

	public static final Field getField(Object obj, String fieldName)
			throws NoSuchFieldException {
		try {
			Class<?> cls = obj.getClass();
			for (; !cls.equals(Object.class); cls = cls.getSuperclass()) {
				Field[] field = cls.getDeclaredFields();
				for (Field f : field) {
					if (f.getName().equals(fieldName)) {
						return f;
					}
				}
			}
		} catch (SecurityException e) {
			log.error(e.getMessage(), e);
		}

		throw new NoSuchFieldException(fieldName);
	}

}
